package com.sl.biz.modular.process.handler;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.alibaba.druid.util.JdbcUtils;
import com.sl.biz.modular.datasource.dao.domain.entity.ProcessDataSourceDO;
import com.sl.biz.modular.datasource.service.DatasourceCustomerService;
import com.sl.biz.modular.process.controller.request.ProcessRunHistoryQueryProcessListRequest;
import com.sl.biz.modular.process.controller.request.ProcessRunHistoryQueryProcessStepDataListRequest;
import com.sl.biz.modular.process.controller.request.ProcessRunHistoryQueryProcessStepListRequest;
import com.sl.biz.modular.process.controller.response.ProcessRunHistoryListVO;
import com.sl.biz.modular.process.controller.response.ProcessRunHistoryStepListVO;
import com.sl.biz.modular.process.controller.response.ProcessVO;
import com.sl.biz.modular.process.dao.domain.entity.ProcessConfigDO;
import com.sl.biz.modular.process.service.ProcessConfigBizService;
import com.sl.core.utils.JsonUtil;
import com.sl.core.engine.rowset.ProcessFileRowSet;
import com.zaxxer.hikari.HikariDataSource;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import javax.sql.DataSource;
import java.io.File;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
public class ProcessRunHistoryFileHandler implements ProcessRunHistoryHandler, DatasourceCustomerService {
    private final ProcessConfigBizService processConfigBizService;

    @Override
    public String type() {
        ProcessFileRowSet processFileRowSet = new ProcessFileRowSet(null);
        return processFileRowSet.typeCode();
    }

    @Override
    public List<ProcessRunHistoryListVO> processList(ProcessRunHistoryQueryProcessListRequest processListRequest) {
        //找到所有本地流程信息
        List<String> dateList = processListRequest.getDateList();
        String keywords = processListRequest.getKeywords();
        if (CollUtil.isEmpty(dateList)) {
            dateList = runDateList();
        }
        if (CollUtil.isEmpty(dateList)) {
            return Collections.emptyList();
        }
        ProcessFileRowSet processFileRowSet = new ProcessFileRowSet(null);
        List<Map<String, Object>> maps = processFileRowSet.searchProcessList(dateList);
        List<ProcessRunHistoryListVO> list = JsonUtil.toList(maps, ProcessRunHistoryListVO.class);
        //查询流程名称
        if (CollUtil.isEmpty(list)) {
            return list;
        }
        List<String> processIds = list.stream().map(ProcessRunHistoryListVO::getProcessId).distinct().toList();
        List<ProcessVO> byIds = processConfigBizService.getByIds(processIds);
        if (CollUtil.isEmpty(byIds)) {
            return list;
        }
        Map<String, ProcessVO> processVOMap = byIds.stream().collect(Collectors.toMap(v -> v.getId(), Function.identity(), (k1, k2) -> k1));

        for (ProcessRunHistoryListVO processRunHistoryListVO : list) {
            ProcessVO processVO = processVOMap.get(processRunHistoryListVO.getProcessId());
            Optional.ofNullable(processVO).ifPresent(v -> {
                processRunHistoryListVO.setProcessName(v.getProcessName());
            });
        }

        return list.stream().sorted(Comparator.comparing(v -> {
            return StrUtil.concat(true, v.getProcessId(), "_", v.getProcessVersion(), "_", v.getTid());
        })).filter(v -> {
            if (StrUtil.isBlank(keywords)) {
                return true;
            }
            return StrUtil.containsAnyIgnoreCase(v.getProcessName(), keywords);
        }).toList();
    }

    @Override
    public List<String> runDateList() {
        File rootFile = ProcessFileRowSet.getBaseRootFile();

        List<File> files = FileUtil.loopFiles(rootFile, 1, null);

        return files.stream().filter(v -> !StrUtil.containsAnyIgnoreCase(v.getName(), "Ds_Store")).map(File::getName).toList();
    }

    @Override
    public List<ProcessRunHistoryStepListVO> stepList(ProcessRunHistoryQueryProcessStepListRequest processListRequest) {
        ProcessFileRowSet processFileRowSet = new ProcessFileRowSet(null);
        List<Map<String, Object>> maps = processFileRowSet.searchStepList(
                processListRequest.getDate(),
                processListRequest.getProcessId(),
                processListRequest.getProcessVersion(),
                processListRequest.getTid(),
                processListRequest.getDbFile()
        );
        return JsonUtil.toList(maps, ProcessRunHistoryStepListVO.class);
    }

    @Override
    public Map<String, Object> stepDataList(ProcessRunHistoryQueryProcessStepDataListRequest processListRequest) {
        ProcessFileRowSet processFileRowSet = new ProcessFileRowSet(null);
        Map<String, Object> dataRows = processFileRowSet.searchStepDataList(
                processListRequest.getDate(),
                processListRequest.getProcessId(),
                processListRequest.getProcessVersion(),
                processListRequest.getTid(),
                processListRequest.getDbFile(),
                processListRequest.getSource(),
                processListRequest.getTarget()
        );
        return dataRows;
    }


    @Override
    public ProcessDataSourceDO getById(String id) {

        String s = URLUtil.decode(Base64.decodeStr(id));
        ProcessRunHistoryQueryProcessStepDataListRequest processListRequest = JsonUtil.toBean(s, ProcessRunHistoryQueryProcessStepDataListRequest.class);
        ProcessFileRowSet processFileRowSet = new ProcessFileRowSet(null);
        DataSource dataSource = processFileRowSet.getDataSource(processListRequest.getDate(),
                processListRequest.getProcessId(),
                processListRequest.getProcessVersion(),
                processListRequest.getTid(),
                processListRequest.getDbFile(),
                processListRequest.getSource(),
                processListRequest.getTarget());

        HikariDataSource hikariDataSource = (HikariDataSource) dataSource;
        ProcessConfigDO processConfigDO = new ProcessConfigDO();
        processConfigDO.setId(processListRequest.getProcessId());
        ProcessVO byId = processConfigBizService.getById(processConfigDO);
        if(ObjectUtil.isNull(byId)){
//            return null;
            byId = new ProcessVO();
        }
        ProcessDataSourceDO processDataSourceDO = new ProcessDataSourceDO();
        processDataSourceDO.setDatasourceCode(byId.getProcessCode());
        processDataSourceDO.setDatasourceName(byId.getProcessName());
        processDataSourceDO.setDriverClassName(hikariDataSource.getDriverClassName());
        processDataSourceDO.setUsername(hikariDataSource.getUsername());
//        processDataSourceDO.setDatabase(hikariDataSource.da);
        processDataSourceDO.setPassword(hikariDataSource.getPassword());
        processDataSourceDO.setIp("LOCAL");
        processDataSourceDO.setPort("-1");
        processDataSourceDO.setUrl(hikariDataSource.getJdbcUrl());
        processDataSourceDO.setDbTypeCode(JdbcUtils.getDbType(processDataSourceDO.getUrl(), processDataSourceDO.getDriverClassName()));
        processDataSourceDO.setDisableFlag(0);
        processDataSourceDO.setOrgId(byId.getOrgId());
        processDataSourceDO.setId(id);
        return processDataSourceDO;
    }
}
